package proyectos.cibertec.core.base.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Transactional;

import proyectos.cibertec.core.base.dao.EntityDao;

public class EntityDaoImpl<E> implements EntityDao<E> {

	@PersistenceContext
	protected EntityManager entityManager;

	protected E instance;
	private Class<E> entityClass;

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	@Transactional
	public void persist(E e) throws Exception {
		getEntityManager().persist(e);
	}

	@Transactional
	public void merge(E e) throws Exception {
		getEntityManager().merge(e);

	}

	@Transactional
	public void remove(Object id) throws Exception {
		getEntityManager().remove((E) getEntityManager().find(getEntityClass(), id));
	}

	@SuppressWarnings("unchecked")
	public E findById(Object id) throws Exception {
		return (E)getEntityManager().find(getClass(), id);
	}

	@SuppressWarnings("unchecked")
	public Class<E> getEntityClass() throws Exception{
		if(entityClass==null){
			Type type = getClass().getGenericSuperclass();
			if(type instanceof ParameterizedType){
			ParameterizedType paramType = (ParameterizedType)type;
			if(paramType.getActualTypeArguments().length==2){
				if(paramType.getActualTypeArguments()[1] instanceof TypeVariable){
					throw new IllegalArgumentException("Could not guess entity class by reflection");
				}else{
					entityClass = (Class<E>) paramType.getActualTypeArguments()[1];
				}
			}else{
				entityClass = (Class<E>) paramType.getActualTypeArguments()[0];
			}
			}
		}
		return entityClass;
	}
	
}
